package erfgame.core.graphics.renderer;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;


import erfgame.core.Rotation;
import erfgame.core.entity.Entity;

public abstract class AbstractEntityRendererProxy implements EntityRenderer, RendererUpdateListener {

	private EntityRenderer proxied;
	private boolean started;
	private RendererUpdateListener updateListener;
	
	public int getDepth(Rotation rotation) {
		return proxied.getDepth(rotation);
	}

	public Dimension getDimension() {
		return proxied.getDimension();
	}

	public Entity getEntity() {
		return proxied.getEntity();
	}

	public Point getGrabPoint() {
		return proxied.getGrabPoint();
	}

	public int getType() {
		// TODO should we override?
		return proxied.getType();
	}

	public void setUpdateListener(RendererUpdateListener listener) {
		this.updateListener = listener;
	}

	public void start() {
		this.started = true;
		this.proxied.start();
	}

	public void stop() {
		this.started = false;
		this.proxied.stop();
	}

	public boolean contains(int lx, int ly) {
		return proxied.contains(lx, ly);
	}

	public void render(Graphics g, int x, int y) {
		proxied.render(g, x, y);
	}

	public void rendererUpdated(RendererUpdateType type, Object state) {
		fireUpdate( type, state );
	}
	
	protected void fireUpdate( RendererUpdateType type, Object state ) {
		if( this.updateListener != null ) {
			this.updateListener.rendererUpdated(type, state);			
		}
	}
	
	public EntityRenderer getProxied() {
		return this.proxied;
	}

	public void setProxied( EntityRenderer proxied ) {
		EntityRenderer oldProxied = this.proxied;
		if( this.proxied != null ) {
			this.proxied.setUpdateListener( null );
			if( this.started ) {
				this.proxied.stop();
			}
		}
		this.proxied = proxied;
		if( this.started && proxied != null ) {
			proxied.start();
		}
		Dimension oldDimension;
		Point oldGrabPoint;
		if( oldProxied != null ) {
			oldDimension = oldProxied.getDimension();
			oldGrabPoint = oldProxied.getGrabPoint();
		} else {
			oldDimension = null;
			oldGrabPoint = null;
		}
		Dimension newDimension;
		Point newGrabPoint;
		if( proxied != null ) {
			newDimension = proxied.getDimension();
			newGrabPoint = proxied.getGrabPoint();
		} else {
			newDimension = null;
			newGrabPoint = null;
		}
		
		// the child renderer size may have changed, in which case this is a bounds change!
		if( newGrabPoint == null || newDimension == null || !newGrabPoint.equals( oldGrabPoint ) || !newDimension.equals( oldDimension ) ) {
			this.fireUpdate( RendererUpdateType.bounds, new RendererBoundsChangeEvent( oldGrabPoint, oldDimension, newGrabPoint, newDimension ) );
		} else {
			this.fireUpdate( RendererUpdateType.content, null );
		}
		// only listen on the child after as this may also fire updates which we wish to ignore (already done above)
		if( proxied != null ) {
			proxied.setUpdateListener( this );
		}
	}
	

}
